/* -*- Mode: C++; c-basic-offset: 4; -*- */
// Copyright (C) 2003, 2004 by BiRC -- Bioinformatics Research Center
//                             University of Aarhus, Denmark
//                             Contact: Thomas Mailund <mailund@birc.dk>

#ifndef NUMBERS_HH
#define NUMBERS_HH

#include <iostream>
#include <cassert>

typedef long long large_int_t;


class MiniRational {
    large_int_t numerator;
	large_int_t denominator; //should probably always be around 2

	void shorten() {
		//fixme this is just by observing prints
		//it is possible
		if(numerator % denominator == 0) {
			numerator = numerator / denominator;
			denominator = 1;
		}
	}

public:
	MiniRational() { 
		numerator = (large_int_t)0;
		denominator = (large_int_t)1;
	};
    
	MiniRational(const large_int_t &i) {
				numerator = i;
				denominator = (large_int_t)1;
    }
    MiniRational(signed long i, signed long j) {
		numerator = i;
		denominator = j;
    }

    ~MiniRational() {
    }

    bool is_zero() const {
				return numerator == 0;
    }

    large_int_t to_int() const {
		MiniRational res = *this;
		res.shorten();
		assert(res.denominator == 1);
		return res.numerator;
    }

    MiniRational operator+(const MiniRational &other) const {
				MiniRational res;
				res.numerator = numerator * other.denominator
					+ other.numerator * denominator;
				res.denominator = denominator * other.denominator;
				
				res.shorten();
				//fixme
				//assert(denominator == other.denominator);
				return res;
    }

    MiniRational operator*(const MiniRational &other) const {
				MiniRational res;
				res.numerator = numerator * other.numerator;
				res.denominator = denominator * other.denominator;

				res.shorten();
				
				return res;
    }
    MiniRational operator*(unsigned int other) const {
		MiniRational res;
		res.numerator = numerator * other;

		res.shorten();
		return res;
    }

    MiniRational &operator*=(const MiniRational &other) {
		numerator *= other.numerator;
		denominator *= other.denominator;

		shorten();
		return *this;
    }

    bool operator==(const MiniRational &other) const {
		//fixme is this right, probably not
		return numerator == other.numerator && denominator == other.denominator;
    }

	bool operator<(const MiniRational &other) const {
		//fixme
		return numerator < other.numerator;
    }
	
    void print(std::ostream &os) const {
		os << numerator;
		if(denominator != 1) {
			os << "/" << denominator;
		} 
    }
	
	friend inline std::ostream &operator<<(std::ostream &os, const MiniRational &r) {
		r.print(os);
		return os;
	}
};

//typedef Rational rational_t;
typedef MiniRational rational_t;

#endif // NUMBERS_HH
